spb/wp-spboucher-ai
Public
1"use client";2import { useState } from "react";3export function UploadForm({ paperId, csrf, nextNo }: { paperId: string; csrf: string; nextNo: number }) {4 const [msg, setMsg] = useState<string | null>(null); const [busy, setBusy] = useState(false);5 const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {6 e.preventDefault(); setBusy(true); setMsg(null); const fd = new FormData(e.currentTarget);7 try { const r = await fetch("/api/admin/upload", { method: "POST", body: fd, headers: { "x-csrf-token": csrf } }); const j = await r.json(); if (!r.ok) throw new Error(j.error ?? r.statusText); setMsg(`Uploaded ${j.label} (sha256 ${String(j.sha256).slice(0, 12)}…). Processing queued.`); setTimeout(() => location.reload(), 1200); }8 catch (err) { setMsg("Error: " + (err as Error).message); } finally { setBusy(false); }9 };10 return (<form onSubmit={onSubmit} className="grid sm:grid-cols-[1fr_8rem_10rem_1fr_auto] gap-2 items-end text-sm">11 <input type="hidden" name="paper_id" value={paperId} />12 <label className="block"><span className="label">PDF</span><input type="file" name="file" accept="application/pdf" required className="input mt-1 !py-1.5" /></label>13 <label className="block"><span className="label">Label</span><input name="label" defaultValue={`v${nextNo}`} className="input mt-1" /></label>14 <label className="block"><span className="label">Date (YYYY-MM[-DD])</span><input name="released_on" className="input mt-1" /></label>15 <label className="block"><span className="label">Description</span><input name="description" className="input mt-1" placeholder="Revised manuscript" /></label>16 <label className="flex items-center gap-2 pb-2"><input type="checkbox" name="make_current" defaultChecked /> current</label>17 <button className="btn btn-primary btn-sm sm:col-span-5 justify-self-start" disabled={busy}>{busy ? "Uploading…" : "Upload version"}</button>18 {msg && <p className="sm:col-span-5 text-xs text-fg-2">{msg}</p>}19 </form>);20}21